extern crate argparse;
extern crate console;
extern crate md5;
extern crate reqwest;

#[macro_use]
extern crate serde_derive;

use argparse::{ArgumentParser, Print, Store};
use console::style;
use reqwest::Client;
use std::collections::HashMap;
use std::string::String;

fn get_sign(params: &mut HashMap<&str, &str>) -> String {
    let _key = "16519bb6022c324489d8dd822466bcgf";
    let mut keys: Vec<_> = params.keys().collect();
    keys.sort();
    let mut qs = String::from("");
    for k in keys {
        qs.push_str(k);
        qs.push_str("=");
        qs.push_str(params[k]);
        qs.push_str("&");
    }
    qs.push_str("key=");
    qs.push_str(_key);
    format!("{:x}", md5::compute(qs))
}

#[derive(Debug, Deserialize)]
struct Message {
    msg: String,
    success: bool,
}

impl Default for Message {
    fn default() -> Message {
        Message {
            msg: "".to_string(),
            success: false,
        }
    }
}

#[derive(Debug)]
struct Options {
    mobile: String,
    ip: String,
    code: String,
    host: String,
}

fn main() {
    let mut options = Options {
        mobile: "".to_string(),
        ip: "127.0.0.1".to_string(),
        code: "".to_string(),
        host: "http://localhost:8092".to_string(),
    };
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("send code message");
        ap.refer(&mut options.mobile)
            .add_argument("MOBILE", Store, "手机号")
            .required();
        ap.refer(&mut options.code)
            .add_argument("CODE", Store, "验证码")
            .required();
        ap.refer(&mut options.ip)
            .add_option(&["--ip"], Store, "用户IP");
        ap.refer(&mut options.host)
            .add_option(&["--host"], Store, "接口host");
        ap.add_option(
            &["-v", "--version"],
            Print("1.0.0".to_string()),
            "Show version",
        );
        ap.parse_args_or_exit();
    }
    let mut sign: String = "".to_string();
    let mut params = HashMap::new();
    params.insert("mobile", options.mobile.as_str());
    params.insert("code", options.code.as_str());
    params.insert("ip", options.ip.as_str());
    sign = get_sign(&mut params);
    params.insert("sign", &sign);
    let client = Client::new();
    let mut api = String::from(options.host);
    api.push_str("/xfky/sms/send/code/bindMobile");
    match client.post(api.as_str()).json(&params).send() {
        Ok(mut response) => {
            let message: Message = response.json().unwrap();
            if message.success {
                println!("发送成功： {}", style(message.msg).green());
            } else {
                println!("发送失败： {}", style(message.msg).red());
            }
        }
        Err(error) => {
            println!("failure： {:?}", style(error).red());
        }
    };
}
